package razor.blade;

import javafx.beans.*;
import javafx.beans.Observable;
import javafx.beans.binding.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.geometry.*;
import javafx.scene.input.*;
import tee.binding.*;

public class Tow {
    private Numeric x;
    private Numeric y;
    private Numeric shiftX;
    private Numeric shiftY;
    private Group root;
    private Group contentGroup;
    private double pressX = 0;
    private double pressY = 0;
    private Task onShift;
    private Rectangle mouseWatcher;
    public Node node() {
        return root;
    }
    public Tow content(Node n) {
        contentGroup.getChildren().clear();
        contentGroup.getChildren().add(n);
        return this;
    }
    public Tow x(double it) {
        x.value(it);
        return this;
    }
    public Tow x(int it) {
        x.value(it);
        return this;
    }
    public Numeric x() {
        return x;
    }
    public Tow x(It<Double> it) {
        x.bind(it);
        return this;
    }
    public Tow y(double it) {
        y.value(it);
        return this;
    }
    public Tow y(int it) {
        y.value(it);
        return this;
    }
    public Numeric y() {
        return y;
    }
    public Tow y(It<Double> it) {
        y.bind(it);
        return this;
    }
    public Numeric shiftX() {
        return shiftX;
    }
    public Numeric shiftY() {
        return shiftY;
    }
    public Tow onShift(Task it) {
        onShift=it;
        return this;
    }
    public Tow cursor(Cursor it) {
        mouseWatcher.setCursor(it);
        return this;
    }
    //public void onDrag(double x, double y) {
    //}
    public Tow() {
        x = new Numeric().value(0);
        y = new Numeric().value(0);
        shiftX = new Numeric().value(0);
        shiftY = new Numeric().value(0);
        root = new Group();
        contentGroup = new Group();
        onShift = new Task() {
            @Override
            public void doTask() {
                x.value(shiftX.value());
                y.value(shiftY.value());
            }
        };
        /*System.out.println("--------------------");
        System.out.println(contentGroup.translateXProperty());
        System.out.println(new Tee<Double>(x));
        System.out.println("*********************************");*/
        contentGroup.translateXProperty().bind(new Tee<Double>(x));
        contentGroup.translateYProperty().bind(new Tee<Double>(y));
        root.getChildren().add(contentGroup);
        mouseWatcher = new Rectangle();
        mouseWatcher.xProperty().bind(contentGroup.translateXProperty());
        mouseWatcher.yProperty().bind(contentGroup.translateYProperty());
        mouseWatcher.setWidth(50);
        mouseWatcher.setHeight(50);
        mouseWatcher.setFill(Color.web("#00000001"));
        mouseWatcher.setCursor(Cursor.MOVE);
        mouseWatcher.setOnMouseDragged(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent event) {
                double dX = event.getScreenX() - pressX;
                double dY = event.getScreenY() - pressY;
                pressX = event.getScreenX();
                pressY = event.getScreenY();
                //System.out.println(dX+":"+ dY);
                //System.out.println(contentGroup.getTranslateY()+" - "+y.get());
                shiftX.value(x.value() + dX);
                shiftY.value(y.value() + dY);
                if (onShift != null) {
                    onShift.start();
                }
            }
        });
        mouseWatcher.setOnMousePressed(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent event) {
                pressX = event.getScreenX();
                pressY = event.getScreenY();
            }
        });
        root.getChildren().add(mouseWatcher);
        ReadOnlyObjectProperty<Bounds> bnds = contentGroup.boundsInParentProperty();
        bnds.addListener(new ChangeListener<Bounds>() {
            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
                mouseWatcher.setWidth(contentGroup.getBoundsInLocal().getWidth());
                mouseWatcher.setHeight(contentGroup.getBoundsInLocal().getHeight());
            }
        });
    }
}
